package org.gongliang.service.sys;

import java.util.List;

import javax.annotation.PostConstruct;

import org.gongliang.common.base.CRUDService;
import org.gongliang.common.task.QuartzJobFactory;
import org.gongliang.common.task.QuartzJobFactoryDisallowConcurrentExecution;
import org.gongliang.dao.sys.TaskDao;
import org.gongliang.entity.sys.Task;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
* 
* @author 龚亮
* @version 1.0
* @date 2017年05月07日 05:14:22
*/
@Service
public class TaskService extends CRUDService<TaskDao, Task> {

	@Autowired
	private SchedulerFactoryBean schedulerFactoryBean;

	/**
	 * 更改任务状态
	 * 
	 * @param scheduleJob
	 * @return
	 * @throws SchedulerException
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public boolean changeJobStatus(Task task) throws SchedulerException {
		int i = baseDao.updateById(task);
		task = baseDao.findById(task.getId().toString());
		if (Task.STATUS_CEASE.equals(task.getStatus())) {// 停止任务
			deleteJob(task);
		} else if (Task.STATUS_RESUME.equals(task.getStatus())) {// 恢复任务
			resumeJob(task);
		} else if (Task.STATUS_RUNNING.equals(task.getStatus())) {// 立即执行任务
			addJob(task);
		} else if (Task.STATUS_STOP.equals(task.getStatus())) {// 暂停任务
			pauseJob(task);
		}
		return retBool(i);
	}

	/**
	 * 添加任务
	 * 
	 * @param job
	 * @throws SchedulerException
	 */
	@SuppressWarnings("unchecked")
	public void addJob(Task task) throws SchedulerException {
		if (task == null || Task.STATUS_CEASE.equals(task.getStatus()) || Task.STATUS_RESUME.equals(task.getStatus())
				|| Task.STATUS_STOP.equals(task.getStatus())) {
			return;
		}
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());

		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);

		// 不存在，创建一个
		if (null == trigger) {
			Class<?> clazz = Task.CONCURRENT_IS.equals(task.getIsConcurrent()) ? QuartzJobFactory.class
					: QuartzJobFactoryDisallowConcurrentExecution.class;
			JobDetail jobDetail = JobBuilder.newJob((Class<? extends Job>) clazz)
					.withIdentity(task.getJobName(), task.getJobGroup()).build();
			jobDetail.getJobDataMap().put("scheduleJob", task);
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCron());
			trigger = TriggerBuilder.newTrigger().withIdentity(task.getJobName(), task.getJobGroup())
					.withSchedule(scheduleBuilder).build();
			scheduler.scheduleJob(jobDetail, trigger);
		} else {
			// Trigger已存在，那么更新相应的定时设置
			CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCron());
			// 按新的cronExpression表达式重新构建trigger
			trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
			// 按新的trigger重新设置job执行
			scheduler.rescheduleJob(triggerKey, trigger);
		}
	}

	/**
	 * 初始化，动态定时器
	 * 
	 * @throws Exception
	 */
	@PostConstruct
	public void init() throws Exception {
		// 这里获取任务信息数据
		List<Task> jobList = baseDao.findAll(null);
		for (Task task : jobList) {
			if ("0".equals(task.getStatus())) {// 停止任务
				deleteJob(task);
			} else if ("4".equals(task.getStatus())) {// 恢复任务
				resumeJob(task);
			} else if ("2".equals(task.getStatus())) {// 立即执行任务
				addJob(task);
			} else if ("3".equals(task.getStatus())) {// 暂停任务
				pauseJob(task);
			}
		}
	}

	/**
	 * 暂停一个job
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void pauseJob(Task task) throws SchedulerException {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
		scheduler.pauseJob(jobKey);
	}

	/**
	 * 恢复一个job
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public void resumeJob(Task task) throws SchedulerException {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
		scheduler.resumeJob(jobKey);
	}

	/**
	 * 删除一个job
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	public void deleteJob(Task task) throws SchedulerException {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
		scheduler.deleteJob(jobKey);
	}

	/**
	 * 立即执行job
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	public void runAJobNow(Task task) throws SchedulerException {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobKey jobKey = JobKey.jobKey(task.getJobName(), task.getJobGroup());
		scheduler.triggerJob(jobKey);
	}

	/**
	 * 更新job时间表达式
	 * 
	 * @param scheduleJob
	 * @throws SchedulerException
	 */
	public void updateJobCron(Task task) throws SchedulerException {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		TriggerKey triggerKey = TriggerKey.triggerKey(task.getJobName(), task.getJobGroup());
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(task.getCron());
		trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
		scheduler.rescheduleJob(triggerKey, trigger);
	}
}
